package com.credit.mola.app.weight

import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.text.Editable
import android.text.InputFilter
import android.text.InputType
import android.text.TextUtils
import android.text.TextWatcher
import android.text.method.HideReturnsTransformationMethod
import android.text.method.PasswordTransformationMethod
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.credit.mola.app.R

/**
 * Sikadwa
 * @Author wwdeng
 * @CreateTime: 2024/4/15 18:13
 * @Annotation：验证码输入框
 */
class VerifyEditText @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0): LinearLayout(context, attrs, defStyleAttr) {
    private val mTextViewList: MutableList<TextView> = ArrayList()
    private val mRelativeLayouts: MutableList<RelativeLayout> = mutableListOf()
    private val mCursorViews: MutableList<View> = mutableListOf()
    private var mShowCursor = false
    private var mCursorColor: Int = Color.parseColor("#FFFFFF")
    private var mEditText: EditText? = null
    private var drawableNormal: Drawable? = null//未选中背景
    private var drawableSelected: Drawable? = null//选中有值背景
    private var drawableSelectedEnable: Drawable? = null//选中无值背景
    private var drawableWrong: Drawable? = null//错误背景
    private var textColor = 0//字体颜色
    private var textColorWrong = 0//错误字体颜色
    private var mContext: Context? = null
    private var valueAnimator: ValueAnimator? = null
    private var mItemCount = 0
    //输入内容是否正确
    private var isWrong = false

    //输入完成监听
    private var mInputCompleteListener: InputCompleteListener? = null

    init {
        init(context, attrs)
    }

    private fun init(context: Context, attrs: AttributeSet?) {
        mContext = context
        orientation = HORIZONTAL
        gravity = Gravity.CENTER
        @SuppressLint("CustomViewStyleable")
        val obtainStyledAttributes = getContext().obtainStyledAttributes(attrs, R.styleable.verify_EditText)
        drawableNormal = obtainStyledAttributes.getDrawable(R.styleable.verify_EditText_verify_background_normal)
        drawableSelected = obtainStyledAttributes.getDrawable(R.styleable.verify_EditText_verify_background_selected)
        drawableSelectedEnable = obtainStyledAttributes.getDrawable(R.styleable.verify_EditText_verify_background_selected_enable)
        drawableWrong = obtainStyledAttributes.getDrawable(R.styleable.verify_EditText_verify_background_wrong)
        textColor = obtainStyledAttributes.getColor(R.styleable.verify_EditText_verify_textColor, ContextCompat.getColor(context, android.R.color.black))
        textColorWrong = obtainStyledAttributes.getColor(R.styleable.verify_EditText_verify_textColor_wrong, ContextCompat.getColor(context, android.R.color.black))
        val textBackgroundColor = obtainStyledAttributes.getColor(R.styleable.verify_EditText_verify_text_backgroundColor, ContextCompat.getColor(context, android.R.color.black))
        mItemCount = obtainStyledAttributes.getInt(R.styleable.verify_EditText_verify_count, DEFAULT_ITEM_COUNT)
        val inputType = obtainStyledAttributes.getInt(R.styleable.verify_EditText_verify_inputType, InputType.TYPE_CLASS_NUMBER)
        val passwordVisibleTime = obtainStyledAttributes.getInt(R.styleable.verify_EditText_verify_password_visible_time, DEFAULT_PASSWORD_VISIBLE_TIME)
        val width = obtainStyledAttributes.getDimension(R.styleable.verify_EditText_verify_width, DEFAULT_ITEM_WIDTH.toFloat()).toInt()
        val height = obtainStyledAttributes.getDimension(R.styleable.verify_EditText_verify_height, 0f).toInt()
        val cursorWidth = obtainStyledAttributes.getDimension(R.styleable.verify_EditText_cursor_width, 1F).toInt()
        mCursorColor = obtainStyledAttributes.getColor(R.styleable.verify_EditText_cursor_color, ContextCompat.getColor(context, android.R.color.black))
        mShowCursor = obtainStyledAttributes.getBoolean(R.styleable.verify_EditText_show_cursor, false)
        val cursorHeight = obtainStyledAttributes.getDimension(R.styleable.verify_EditText_cursor_height, 20F).toInt()
        val margin = obtainStyledAttributes.getDimension(R.styleable.verify_EditText_verify_margin, DEFAULT_ITEM_MARGIN.toFloat()).toInt()
        val textSize = px2sp(context, obtainStyledAttributes.getDimension(R.styleable.verify_EditText_verify_textSize, sp2px(context, DEFAULT_ITEM_TEXT_SIZE.toFloat()).toFloat())).toFloat()
        val password = obtainStyledAttributes.getBoolean(R.styleable.verify_EditText_verify_password, false)
        obtainStyledAttributes.recycle()
        if (mItemCount < 2) mItemCount = 2 //最少 2 个 item
        mEditText = EditText(context)
        mEditText?.run {
            mEditText?.inputType = inputType
            layoutParams = LayoutParams(1, 1)
            isCursorVisible = false
            background = null
            filters = arrayOf<InputFilter>(InputFilter.LengthFilter(mItemCount)) //限制输入长度为 count
            addTextChangedListener(object : TextWatcher {
                override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
                }

                override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                    isWrong = false
                    if (before == 0 && (start + count) < 7) {// 输入
                        if (count > 1) {// 有复制内容进来
                            for (i in start until start + count) {
                                val input = s.subSequence(i, i + 1) // 获取新输入的字
                                inputText(i, password, passwordVisibleTime, input.toString())
                            }
                        } else {// 逐步输入
                            inputText(start, password, passwordVisibleTime, s.subSequence(start, s.length).toString())
                        }
                    } else {// 删除
                        val textView = mTextViewList[start] // 获取对应的 textview
                        textView.text = ""
                        setTextViewBackground(textView, drawableNormal)
                    }
                    if (mInputCompleteListener != null && s.length < mTextViewList.size){
                        mInputCompleteListener?.textChange(s.toString())
                    }

                    if (mInputCompleteListener != null && s.length == mTextViewList.size)
                        mInputCompleteListener?.complete(s.toString())
                }

                override fun afterTextChanged(s: Editable) {
                    setCursorColor()
                }
            })
        }
        addView(mEditText)
        //点击弹出软键盘
        setOnClickListener { v: View? ->
            mEditText?.requestFocus()
            showSoftKeyBoard()
        }
        //遍历生成 textview
        for (i in 0 until mItemCount) {
            val relativeLayout = RelativeLayout(context)
            relativeLayout.layoutParams = getRelativeLayoutParams(i, margin, width, height)
            mRelativeLayouts.add(relativeLayout)

            val textView = TextView(context)
            textView.textSize = textSize
            textView.maxEms = 1
            textView.maxLines = 1
            textView.setTypeface(Typeface.create(Typeface.DEFAULT,Typeface.BOLD))
//            textView.gravity = Gravity.CENTER
            textView.setTextColor(textColor)
//            textView.setBackgroundColor(textBackgroundColor)
//            textView.layoutParams = layoutParams
            initTextView(textView)
            setTextViewBackground(textView, drawableNormal)
//            addView(textView)
            relativeLayout.addView(textView)
            mTextViewList.add(textView)

            if (mShowCursor) {
                val cursorView = View(context)
                initCursorView(cursorView, cursorWidth, cursorHeight)
                relativeLayout.addView(cursorView)
                mCursorViews.add(cursorView)
            }
            relativeLayout.setBackgroundColor(textBackgroundColor)
            addView(relativeLayout)
        }

        setCursorColor()
    }

    private fun getRelativeLayoutParams(i: Int, margin: Int, width: Int, height: Int): LayoutParams {
        val layoutParams = LayoutParams(width, if (height == 0) ViewGroup.LayoutParams.WRAP_CONTENT else height)
        if (i == 0) layoutParams.leftMargin = -1 else layoutParams.leftMargin = margin
        return layoutParams
    }

    private fun initTextView(textView: TextView) {
        val lp: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
        textView.gravity = Gravity.CENTER
        textView.layoutParams = lp
    }

    private fun initCursorView(cursorView: View, cursorWidth: Int, cursorHeight: Int) {
        val lp: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(cursorWidth, cursorHeight)
        lp.addRule(RelativeLayout.CENTER_IN_PARENT)
        lp.addRule(RelativeLayout.CENTER_VERTICAL)
        lp.marginStart = 6
        cursorView.layoutParams = lp
    }

    private fun inputText(start: Int, password: Boolean, passwordVisibleTime: Int, input: String) {
        val textView = mTextViewList[start] // 获取对应的 textview
        textView.text = input
        if (password) { //如果需要密文显示
            textView.transformationMethod = HideReturnsTransformationMethod.getInstance()
            //passwordVisibleTime 毫秒后设置为密文显示
            textView.postDelayed(
                {
                    textView.transformationMethod = PasswordTransformationMethod.getInstance()
                },
                passwordVisibleTime.toLong()
            )
        }
        setTextViewBackground(textView, drawableSelected)
    }

    /**
     * view 添加到窗口时，延迟 500ms 弹出软键盘
     */
    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        mEditText?.postDelayed({ showSoftKeyBoard() }, 500)
    }

    /**
     * 设置背景
     * @param textView
     * @param drawable
     */
    private fun setTextViewBackground(textView: TextView, drawable: Drawable?) {
        if (drawable != null) textView.background = drawable
    }

    private fun setCursorColor() {
        if (mShowCursor) {
            valueAnimator?.cancel()

            for (i in 0 until mItemCount) {
                //设置默认光标颜色为透明
                val cursorView = mCursorViews[i]
                cursorView.setBackgroundColor(Color.TRANSPARENT)

                //设置默认TextView颜色为无值未选中
                val textView = mTextViewList[i]
                if (isWrong){//验证码是否错误
                    textView.setTextColor(textColorWrong)
                    setTextViewBackground(textView, drawableWrong)
                } else {
                    textView.setTextColor(textColor)
                    setTextViewBackground(textView, drawableNormal)
                }
            }

            val index = mEditText?.text?.length ?: 0
            if (index < mItemCount) {
                setCursorView(mCursorViews[index])
                setTextViewBackground(mTextViewList[index], drawableSelectedEnable)
            }
        }
    }

    /**
     * 设置焦点色变换动画
     *
     * @param view
     */
    private fun setCursorView(view: View) {
        this.valueAnimator = ObjectAnimator.ofInt(view, "backgroundColor", mCursorColor, android.R.color.transparent)
        valueAnimator?.run {
            duration = 1300
            repeatCount = -1
            repeatMode = ValueAnimator.RESTART
            setEvaluator { fraction, startValue, endValue -> if (fraction <= 0.5f) startValue else endValue }
            start()
        }
    }

    /**
     * 获取当前输入的内容
     *
     * @return
     */
    val content: String
        get() {
            val text = mEditText?.text
            return if (TextUtils.isEmpty(text)) "" else mEditText?.text.toString()
        }

    /**
     * 清除内容
     */
    fun clearContent() {
        mEditText?.setText("")
        for (i in mTextViewList.indices) {
            val textView = mTextViewList[i]
            textView.text = ""
            setTextViewBackground(textView, drawableNormal)
        }
    }

    /**
     * 设置默认的内容
     *
     * @param content
     */
    fun setDefaultContent(content: String) {
        mEditText?.setText(content)
        mEditText?.requestFocus()
        val chars = content.toCharArray()
        val min = Math.min(chars.size, mTextViewList.size)
        for (i in 0 until min) {
            val aChar = chars[i]
            val s = aChar.toString()
            val textView = mTextViewList[i]
            textView.text = s
            setTextViewBackground(textView, drawableSelected)
        }
        if (mInputCompleteListener != null && min == mTextViewList.size) mInputCompleteListener?.complete(
            content.substring(0, min)
        )
    }

    /**
     * 设置验证码错误样式
     */
    fun setVerifyCodeIsWrong(isWrong: Boolean){
        this.isWrong = isWrong
        setCursorColor()
    }

    /**
     * 显示软键盘
     */
    private fun showSoftKeyBoard() {
        val imm = mContext?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.showSoftInput(mEditText, InputMethodManager.SHOW_FORCED)
    }

    /**
     * 添加输入完成的监听
     *
     * @param inputCompleteListener
     */
    fun addInputCompleteListener(inputCompleteListener: InputCompleteListener) {
        mInputCompleteListener = inputCompleteListener
        val content = mEditText?.text
        if (!TextUtils.isEmpty(content) && content.toString().length == mTextViewList.size) {
            mInputCompleteListener?.complete(content.toString())
        }
    }

    interface InputCompleteListener {
        fun textChange(content: String)
        fun complete(content: String)
    }

    private fun px2sp(context: Context, pxValue: Float): Int {
        val fontScale = context.resources.displayMetrics.scaledDensity
        return (pxValue / fontScale + 0.5f).toInt()
    }

    private fun sp2px(context: Context, spValue: Float): Int {
        val fontScale = context.resources.displayMetrics.scaledDensity
        return (spValue * fontScale + 0.5f).toInt()
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
//        CommonUtil.hideKeyboard(this)
        valueAnimator?.cancel()
    }


    companion object {
        //默认 item 个数为 4 个
        private const val DEFAULT_ITEM_COUNT = 4

        //默认每个 item 的宽度为 100
        private const val DEFAULT_ITEM_WIDTH = 100

        //默认每个 item 的间距为 50
        private const val DEFAULT_ITEM_MARGIN = 50

        //默认每个 item 的字体大小为 14
        private const val DEFAULT_ITEM_TEXT_SIZE = 14

        //默认密码明文显示时间为 200ms，之后密文显示
        private const val DEFAULT_PASSWORD_VISIBLE_TIME = 200
    }
}